<?php
namespace Core\Event;
use Core\Event\Dispatch\Exception as DispatchException;
use Phalcon\Di\Injectable;

class Dispatch extends Injectable
{
    protected function _getAnnotations() {
        $annotations = $this->annotations->get($this->dispatcher->getControllerClass());
        $annotations = array_merge(
            $annotations->getClassAnnotations()->getAnnotations(),
            $annotations->getMethodsAnnotations()[$this->dispatcher->getActiveMethod()]->getAnnotations()
        );
        return $annotations;
    }

    protected function _resolveAnnotation($event) {
        if($annotations = $this->_getAnnotations()) {
            $events = [
                'Before',
                'After'
            ];
            $annotationEvents = [];
            foreach ($annotations as $annotation) {
                $name = ucfirst($annotation->getName());
                if(in_array($name, $events)) {
                    $annotationEvents[$name] = $annotation;
                }
            }
            foreach ($annotationEvents as $name => $annotation) {
                $class = "\\Core\\Event\\Dispatch\\Annotation\\{$name}";
                $object = new $class($annotation);
                if(method_exists($object, $event->getType())) {
                    if(!$object->{$event->getType()}($event)) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    /**
     * Before exception is happening.
     * @param AbstractEvent            $event      Event object.
     * @param Dispatcher       $dispatcher Dispatcher object.
     * @param PhalconException $exception  Exception object.
     * @return bool
     */
    public function beforeException($event, $dispatcher, $exception) {
        $dispatchException = new DispatchException();
        return $dispatchException->beforeException($event, $dispatcher, $exception);
    }

    public function beforeDispatch($event) {
        return $this->_resolveAnnotation($event);
    }

    public function afterDispatch($event) {
        return $this->_resolveAnnotation($event);
    }
}